// ========================================================================
// Copyright (c) 2022 ChangYou, All rights reserved.
// http://www.changyou.com/
// 
// Filename:    FoliageDensityMap.cs
// Time:        2022-08-22 20:41:34
// Author:      xiangjinbao
// Email:       xiangjinbao@cyou-inc.com
// Version:     v2022.0.1
// Description: FoliageDensityMap
// ========================================================================

using UnityEngine;

namespace ProjectTW.Foliage
{
    /// <summary>
    /// 密度信息如下:
    ///
    /// R: 原型索引1的密度值（0-255）
    /// G: 原型索引2的密度值（0-255）
    /// B: 原型索引3的密度值（0-255）
    /// A: 原型索引4的密度值（0-255）
    /// </summary>
    [System.Serializable]
    public class FoliageDensityMap : FoliageMapBase
    {
        /// <summary>
        /// 获取草图路径
        /// </summary>
        /// <param name="foliageInstance"></param>
        /// <returns></returns>
        public static string GetPath(FoliageChunk foliageInstance)
        {
            return FoliageMapUtility.GetMapPath("Density", foliageInstance.AttachedFoliageInstance.Guid, string.Empty);
        }

        public FoliageDensityMap(Texture2D texture, Color32[] pixels, FoliageChunk foliageInstance) : base(texture, pixels, foliageInstance)
        {
        }

        /// <summary>
        /// 重置密度信息
        /// </summary>
        public void ResetDensity()
        {
            for (int i = 0; i < MapWidth; i++)
            {
                for (int j = 0; j < MapWidth; j++)
                {
                    MapPixels[i + j * MapWidth].r = 0;
                    MapPixels[i + j * MapWidth].b = 0;
                }
            }

            SetPixels32();
            Save();
        }

        /// <summary>
        /// 销毁草密度图
        /// </summary>
        public override void Dispose()
        {
            FoliageMapUtility.DisposeMap(Map, GetPath(FoliageInstance));
        }

        /// <summary>
        /// 设置原型密度，根据归一化x, z
        /// </summary>
        /// <param name="x"></param>
        /// <param name="z"></param>
        /// <param name="prototype"></param>
        /// <param name="density"></param>
        /// <returns></returns>
        public void SetPrototypeDensity(int x, int z, byte prototype, byte density)
        {
            SetPrototypeDensity(x + z * MapWidth, prototype, density);
        }
        
        /// <summary>
        /// 设置密度，归一化索引值
        /// </summary>
        /// <param name="index">x + z * width</param>
        /// <param name="prototype"></param>
        /// <param name="density"></param>
        public void SetPrototypeDensity(int index, byte prototype, byte density)
        {
            Color32 pixel = m_MapPixels[index];

            switch (prototype)
            {
                case 1:
                    pixel.r = density;
                    break;
                case 2:
                    pixel.g = density;
                    break;
                case 3:
                    pixel.b = density;
                    break;
                case 4:
                    pixel.a = density;
                    break;
                default:
                    break;
            }
            m_MapPixels[index] = pixel;
        }
        
        /// <summary>
        /// 获取原型对应的密度
        /// </summary>
        /// <param name="x"></param>
        /// <param name="z"></param>
        /// <param name="prototype"></param>
        /// <returns></returns>
        public byte GetPrototypeDensity(int x, int z, byte prototype)
        {
            Color32 pixel = MapPixels[x + z * MapWidth];

            switch (prototype)
            {
                case 1:
                    return pixel.r;
                case 2:
                    return pixel.g;
                case 3:
                    return pixel.b;
                case 4:
                    return pixel.a;
                default:
                    return 0;
            }
        }

        /// <summary>
        /// Mark the densities as dirty.
        /// </summary>
        public void MarkDensitiesDirty()
        {
            FoliageMeshManager.MarkDensitiesDirty();
        }

        public void Save()
        {
            if (Dirty)
            {
                SetPixels32();
#if UNITY_EDITOR
                FoliageMapUtility.SaveMap(this, GetPath(FoliageInstance));
#endif
                Dirty = false;
            }
        }

        public static bool globalDirty
        {
            get
            {
                FoliageManager manager = FoliageManager.Instance;
                FoliageChunk chunk;
                FoliageInstanceObject foliageInstance;

                FoliageSector sector = manager.Sector;

                for (int j = 0; j < sector.FoliageChunks.Count; j++)
                {
                    chunk = sector.FoliageChunks[j];

                    if (!chunk.IsFoliageInstanceAttached)
                    {
                        continue;
                    }

                    foliageInstance = chunk.GetOrCreateFoliageManagerInstance();

                    if (foliageInstance.DensityMap.Dirty)
                    {
                        return true;
                    }
                }

                return false;
            }
        }

        public static void SaveAllMaps()
        {
            FoliageManager manager = FoliageManager.Instance;

            for (int j = 0; j < manager.Sector.FoliageChunks.Count; j++)
            {
                FoliageChunk chunk = manager.Sector.FoliageChunks[j];

                if (!chunk.IsFoliageInstanceAttached)
                {
                    continue;
                }

                FoliageInstanceObject foliageInstance = chunk.GetOrCreateFoliageManagerInstance();
                foliageInstance.DensityMap.Save();
            }
        }
    }
}
